#pragma once
#include "Exception.h"
#include "util_types.h"
#include <cstdint>
#include <cstring>
#include <limits>
#include <vector>
#include <yzrutil.h>

namespace yzrilyzr_lang{
	EBCLASS(StringBuilder){
	private:
	std::vector<uint32_t> code_points;
	public:
	StringBuilder()=default;
	StringBuilder(const String & str){
		append(str);
	}
	StringBuilder(const Object & obj){
		append(obj.toString());
	}
	StringBuilder & append(const Object * obj){
		if(obj)return append(obj->toString());
		return append(U_NULL_STRING);
	}
	StringBuilder & append(const std::shared_ptr<Object> obj){
		if(obj)return append(obj->toString());
		return append(U_NULL_STRING);
	}
	StringBuilder & append(const Object & obj){
		return append(obj.toString());
	}
	StringBuilder & append(const String & str){
		if(str == nullptr)return append(U_NULL_STRING);
		code_points.insert(code_points.end(), str.begin(), str.end());
		return *this;
	}
	StringBuilder & appendCodePoint(uint32_t cp){
		code_points.push_back(cp);
		return *this;
	}
	StringBuilder & duplicate(u_index count){
		if(code_points.empty() || count == 1) return *this;
		if(count == 0){
			code_points.clear();
			return *this;
		}
		// 防止count过大导致内存溢出
		if(0x7fffffff / count < code_points.size()){
			throw OutOfMemoryError("Duplicate count too large");
		}
		auto original=code_points;
		code_points.reserve(original.size() * count);
		for(u_index i=1; i < count; i++){
			code_points.insert(code_points.end(), original.begin(), original.end());
		}
		return *this;
	}
	StringBuilder & deleteRange(u_index start, u_index end){
			// 参数校验
		if(start > end){
			throw IndexOutOfBoundsException("Start index cannot be greater than end index");
		}
		if(end > length()){
			throw IndexOutOfBoundsException("StringIndexOutOfBoundsException");
		}

		// 不需要删除的情况
		if(start == end){
			return *this;
		}

		// 执行删除操作
		code_points.erase(code_points.begin() + start, code_points.begin() + end);
		return *this;
	}

	// 为了保持一致性，也可以添加一个只接受start参数的版本
	StringBuilder & deleteRange(u_index start){
		return deleteRange(start, length());
	}
	StringBuilder & deleteCharAt(u_index i);
	String substring(u_index startInclusive, u_index endExclusive){
		if(startInclusive > endExclusive || endExclusive > length()){
			throw IndexOutOfBoundsException("StringIndexOutOfBoundsException");
		}
		return String(code_points, startInclusive, endExclusive - startInclusive);
	}

	String substring(u_index startInclusive){
		return substring(startInclusive, length());
	}
	u_index length()const{
		return code_points.size();
	}
	StringBuilder & operator+=(const String & str){
		return append(str);
	}
	StringBuilder & operator*=(u_index count){
		return duplicate(count);
	}
	StringBuilder & operator<<(const String & str){
		return append(str);
	}
	uint32_t & operator[](u_index index);
	String toString()const override{
		return String(code_points);
	}
	};
}